<?php
class Warehouse_Allocate extends QDB_ActiveRecord_Abstract
{
	/**
	 * 返回对象的定义
	 *
	 * @static
	 *
	 * @return array
	 */
	static function __define()
	{
		return array
		(
			// 指定该 ActiveRecord 要使用的行为插件
			'behaviors' => '',

			// 指定行为插件的配置
			'behaviors_settings' => array
			(
			    # '插件名' => array('选项' => 设置),
			),

			// 用什么数据表保存对象
			'table_name' => 'warehouse_allocate',

			// 指定数据表记录字段与对象属性之间的映射关系
			// 没有在此处指定的属性，QeePHP 会自动设置将属性映射为对象的可读写属性
			'props' => array
			(
				// 主键应该是只读，确保领域对象的“不变量”
				'id' => array('readonly' => true),

				/**
				 *  可以在此添加其他属性的设置
				 */
				# 'other_prop' => array('readonly' => true),

				/**
				 * 添加对象间的关联
				 */
				# 'other' => array('has_one' => 'Class'),

			),

			/**
			 * 允许使用 mass-assignment 方式赋值的属性
			 *
			 * 如果指定了 attr_accessible，则忽略 attr_protected 的设置。
			 */
			'attr_accessible' => '',

			/**
			 * 拒绝使用 mass-assignment 方式赋值的属性
			 */
			'attr_protected' => 'id',

			/**
			 * 指定在数据库中创建对象时，哪些属性的值不允许由外部提供
			 *
			 * 这里指定的属性会在创建记录时被过滤掉，从而让数据库自行填充值。
			 */
			'create_reject' => '',

			/**
			 * 指定更新数据库中的对象时，哪些属性的值不允许由外部提供
			 */
			'update_reject' => '',

			/**
			 * 指定在数据库中创建对象时，哪些属性的值由下面指定的内容进行覆盖
			 *
			 * 如果填充值为 self::AUTOFILL_TIMESTAMP 或 self::AUTOFILL_DATETIME，
			 * 则会根据属性的类型来自动填充当前时间（整数或字符串）。
			 *
			 * 如果填充值为一个数组，则假定为 callback 方法。
			 */
			'create_autofill' => array
			(
				# 属性名 => 填充值
				# 'is_locked' => 0,
			),

			/**
			 * 指定更新数据库中的对象时，哪些属性的值由下面指定的内容进行覆盖
			 *
			 * 填充值的指定规则同 create_autofill
			 */
			'update_autofill' => array
			(
			),

			/**
			 * 在保存对象时，会按照下面指定的验证规则进行验证。验证失败会抛出异常。
			 *
			 * 除了在保存时自动验证，还可以通过对象的 ::meta()->validate() 方法对数组数据进行验证。
			 *
			 * 如果需要添加一个自定义验证，应该写成
			 *
			 * 'title' => array(
			 *	array(array(__CLASS__, 'checkTitle'), '标题不能为空'),
			 * )
			 *
			 * 然后在该类中添加 checkTitle() 方法。函数原型如下：
			 *
			 * static function checkTitle($title)
			 *
			 * 该方法返回 true 表示通过验证。
			 */
			'validations' => array
			(
			),
		);
	}


/* ------------------ 以下是自动生成的代码，不能修改 ------------------ */

	/**
	 * 开启一个查询，查找符合条件的对象或对象集合
	 *
	 * @static
	 *
	 * @return QDB_Select
	 */
	static function find()
	{
		$args = func_get_args();
		return QDB_ActiveRecord_Meta::instance(__CLASS__)->findByArgs($args);
	}

	/**
	 * 返回当前 ActiveRecord 类的元数据对象
	 *
	 * @static
	 *
	 * @return QDB_ActiveRecord_Meta
	 */
	static function meta()
	{
		return QDB_ActiveRecord_Meta::instance(__CLASS__);
	}


/* ------------------ 以上是自动生成的代码，不能修改 ------------------ */
	/**
	 * 调配单的新建
	 * @param 调配单信息 $allocate
	 * @return 生成成功或失败
	 */
	static function create($allocate)
	{
		$judge = Warehouse_Allocate::judgeCreate($allocate);
		if ($judge['ack'] == SUCCESS)
		{
			$generate_result = Number_Rules::generate('warehouse_allocate', 'DP');
			if ($generate_result['ack'] == SUCCESS)
			{
				$new_allocate = new Warehouse_Allocate();
				$new_allocate->number = $generate_result['number'];
				$new_allocate->status = Q::ini('custom_flag/warehouse_allocate_status/new/value');
				$new_allocate->start_warehouse_id = $allocate['start_warehouse_id'];
				$new_allocate->end_warehouse_id = $allocate['end_warehouse_id'];
				$new_allocate->make_user_id = CURRENT_USER_ID;
				$new_allocate->make_time = CURRENT_DATETIME;
				$new_allocate->notes = $allocate['notes'];
				$new_allocate->save();
				$new_allocate_id = mysql_insert_id();
				$item_result = Warehouse_Allocate_Item::update($allocate['item'], $new_allocate_id);
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => $generate_result['ack'], 'message' => $generate_result['message']);
			}
		}
		else
		{
			return array('ack' => $judge['ack'], 'message' => implode("\n", $judge['message']));
		}
	}
	
	/**
	 * 调配单新建判断检测库存可用（包括）
	 * @param $allocate
	 */
	static function judgeCreate($allocate)
	{
		if ($allocate['item'])
		{
			return Warehouse_Allocate::checkAvialableQuantity($allocate['item'], $allocate['start_warehouse_id'], $allocate['end_warehouse_id']);
		}
		else
		{
			return array('ack' => FAILURE, 'message' => array('没有调配的产品信息！'));
		}
	}
	
	static function edit($allocate)
	{
		$judge_result = Warehouse_Allocate::judgeEdit($allocate);
		if ($judge_result['ack'] == SUCCESS)
		{
			$allocate_edit = Warehouse_Allocate::find('id=?', $allocate['id'])->getOne();
			$allocate_edit->notes = $allocate['notes'];
			$allocate_edit->save();
			Warehouse_Allocate_Item::update($allocate['item'], $allocate['id']);
			return array('ack' => SUCCESS, 'message' => '');
		}
		else
		{
			return array('ack' => FAILURE, 'message' => implode("\n", $judge_result['message']));
		}
	}
	
	static function judgeEdit($allocate)
	{
		$check_in_db = Warehouse_Allocate::find('id=?', $allocate['id'])->asArray()->getOne();
		if ($check_in_db)
		{
			if ($check_in_db['status'] == Q::ini('custom_flag/warehouse_allocate_status/new/value'))
			{
				return Warehouse_Allocate::checkAvialableQuantity($allocate['item'], $check_in_db['start_warehouse_id'], $check_in_db['end_warehouse_id'], $check_in_db['id']);
			}
			else
			{
				return array('ack' => FAILURE, 'message' => '调配单状态有误，不是新单状态');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => '系统不存在该调配单');
		}
	}

	static function delete($allocate_id)
	{
		$result = Warehouse_Allocate::judgeDelete($allocate_id);
		if ($result['ack'] == SUCCESS)
		{
			Warehouse_Allocate_Item::delete($allocate_id);
			Warehouse_Allocate::meta()->deleteWhere('id=?', $allocate_id);
			return array('ack' => SUCCESS, 'message' => '');
		}
		else
		{
			return array('ack' => FAILURE, 'message' => $result['message']);
		}
	}
	
	static function judgeDelete($allocate_id)
	{
		$check_in_db = Warehouse_Allocate::find('id=?', $allocate_id)->asArray()->getOne();
		if ($check_in_db)
		{
			if ($check_in_db['status'] == Q::ini('custom_flag/warehouse_allocate_status/new/value'))
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $check_in_db['number'] . '：调配单状态不是新单状态，不能删除！');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => '系统不存在该调配单，ID=' . $allocate_id);
		}
	}
	
	static function changeNewToConfirm($allocate_ids)
	{
		$message = array();
		foreach ($allocate_ids as $id)
		{
			$judge = Warehouse_Allocate::judgeChangeNewToConfirm($id);
			if ($judge['ack'] == SUCCESS)
			{
				Warehouse_Allocate_Item::changeNewToConfirm($id);
				QDB::getConn()->execute('update warehouse_allocate set status=' . Q::ini('custom_flag/warehouse_allocate_status/confirmed/value') . ', confirm_time=\'' . CURRENT_DATETIME . '\', confirm_user_id=' . CURRENT_USER_ID . ' where id=' . $id);
			}
			else
			{
				$message[] = $judge['message'];
			}
		}
		if ($message)
		{
			return array('ack' => FAILURE, 'message' => implode("\n", $message));
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	static function judgeChangeNewToConfirm($allocate_id)
	{
		$check_in_db = Warehouse_Allocate::find('id=?', $allocate_id)->asArray()->getOne();
		if ($check_in_db)
		{
			if ($check_in_db['status'] == Q::ini('custom_flag/warehouse_allocate_status/new/value'))
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $check_in_db['number'] . '：调配单不是新单状态！');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => '不存在调配单');
		}
	}
	
	static function changeConfirmToReturn($allocate_ids)
	{
		$message = array();
		foreach ($allocate_ids as $id)
		{
			$judge = Warehouse_Allocate::judgeChangeConfirmToArriveOrReturn($id);
			if ($judge['ack'] == SUCCESS)
			{
				Warehouse_Allocate_Item::changeConfirmToReturn($id);
				QDB::getConn()->execute('update warehouse_allocate set status=' . Q::ini('custom_flag/warehouse_allocate_status/returned/value') . ', return_time=\'' . CURRENT_DATETIME . '\', return_user_id=' . CURRENT_USER_ID . ' where id=' . $id);
			}
			else
			{
				$message[] = $judge['message'];
			}
		}
		if ($message)
		{
			return array('ack' => FAILURE, 'message' => implode("\n", $message));
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	static function changeConfirmToArrive($allocate_ids)
	{
		$message = array();
		foreach ($allocate_ids as $id)
		{
			$judge = Warehouse_Allocate::judgeChangeConfirmToArriveOrReturn($id);
			if ($judge['ack'] == SUCCESS)
			{
				Warehouse_Allocate_Item::changeConfirmToArrive($id);
				QDB::getConn()->execute('update warehouse_allocate set status=' . Q::ini('custom_flag/warehouse_allocate_status/arrived/value') . ', arrive_time=\'' . CURRENT_DATETIME . '\', arrive_user_id=' . CURRENT_USER_ID . ' where id=' . $id);
			}
			else
			{
				$message[] = $judge['message'];
			}
		}
		if ($message)
		{
			return array('ack' => FAILURE, 'message' => implode("\n", $message));
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	static function judgeChangeConfirmToArriveOrReturn($allocate_id)
	{
		$check_in_db = Warehouse_Allocate::find('id=?', $allocate_id)->asArray()->getOne();
		if ($check_in_db)
		{
			if ($check_in_db['status'] == Q::ini('custom_flag/warehouse_allocate_status/confirmed/value'))
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $check_in_db['number'] . '：调配单不是已确认状态！');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => '不存在调配单，ID=' . $allocate_id);
		}
	}
	
	/*
	 * 检测可用
	 * @param $products 产品数组
	 * @param $start_warehouse_id 起始仓库
	 * @param $end_warehouse_id 目标仓库
	 * @param $warehouse_allocate_id 调配单id
	 */
	static function checkAvialableQuantity($products, $start_warehouse_id, $end_warehouse_id, $warehouse_allocate_id = 0)
	{
		$message = $item = array();
		foreach ($products as $key => $p)
		{
			$check_in_start = Product_Warehouse::find('product_warehouse.product_basic_id=? and product_warehouse.warehouse_id=?', $p['product_basic_id'], $start_warehouse_id)
				->joinLeft('product_basic', 'number', 'product_basic.id=product_warehouse.product_basic_id')
				->asArray()->getOne();
			$check_in_end = Product_Warehouse::find('product_warehouse.product_basic_id=? and product_warehouse.warehouse_id=?', $p['product_basic_id'], $end_warehouse_id)
				->joinLeft('product_basic', 'number', 'product_basic.id=product_warehouse.product_basic_id')
				->asArray()->getOne();
			if ($check_in_start && $check_in_end)
			{
				if (in_array($check_in_start['number'], $item))
				{
					$item[$check_in_start['number']]['need_quantity'] += $p['quantity'];
				}
				else
				{
					$item[$check_in_start['number']]['need_quantity'] = $p['quantity'];
					$item[$check_in_start['number']]['available_quantity'] = $check_in_start['available_quantity'];
					if ($warehouse_allocate_id)
					{
						$alread_use_quantity = Warehouse_Allocate_Item::find('warehouse_allocate_id=? and product_basic_id=?', $warehouse_allocate_id, $p['product_basic_id'])->getSum('quantity');	
						$item[$check_in_start['number']]['available_quantity'] = $check_in_start['available_quantity'] + $alread_use_quantity;
					}
				}
			}
			else
			{
				$message[] = $key . '：起始或目标仓库不存在该产品';
			}
		}
		foreach ($item as $k => $i)
		{
			if ($i['need_quantity'] > $i['available_quantity'])
			{
				$message[] = $k . '：起始仓可用库存不足！需调拨' . $i['need_quantity']. '，库存剩' . $i['available_quantity'];
			}
		}
		if ($message)
		{
			return array('ack' => FAILURE, 'message' => $message);
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => $message);
		}
	}
	
	
	/**
	 * 财务审核
	 * @param $ids 调拨单id
	 */
	static function financeAudit($ids)
	{
		$message = array();
		foreach ($ids as $key => $id)
		{
			$judge_result = Warehouse_Allocate::judgeFinanceAudit($id);
			if ($judge_result['ack'] == SUCCESS)
			{
				QDB::getConn()->execute('update warehouse_allocate set finance_audit=' . Q::ini('custom_flag/other_io_finance_audit/audited/value') . ',finance_audit_user_id=' . CURRENT_USER_ID . ',finance_audit_time=\'' . CURRENT_DATETIME . '\' where id=' . $id);
			}
			else
			{
				$message[] = 'NO.' . ($key + 1) . ' ' . $judge_result['message'];
			}
		}
		if ($message)
		{
			return array('ack' => FAILURE, 'message' => implode(',', $message));
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	/**
	 * 判断是否可以财务审核
	 * @param $warehouse_allocate_id 调拨单id
	 */	
	static function judgeFinanceAudit($warehouse_allocate_id)
	{
		$warehouse_allocate = Warehouse_Allocate::find('id=?', $warehouse_allocate_id)->asArray()->getOne();
		if ($warehouse_allocate)
		{
			if ($warehouse_allocate['finance_audit'] == Q::ini('custom_flag/warehouse_allocate_finance_audit/unaudited/value'))
			{
				if ($warehouse_allocate['status'] != Q::ini('custom_flag/warehouse_allocate_status/new/value'))
				{
					return array('ack' => SUCCESS, 'message' => '');
				}
				else
				{
					return array('ack' => FAILURE, 'message' => '调拨单' . $warehouse_allocate['number'] . '仓库还没确认!');
				}
			}
			else
			{
				return array('ack' => FAILURE, 'message' => '调拨单已经审核!');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => '调拨单不存在!');
		}
	}
	
	static function search($condition, $cp, $ps)
	{
		$columns = array(
			'warehouse_allocate.*',
			'a.name as start_warehouse_name',
			'b.name as end_warehouse_name',
			'c.name as make_user_name',
			'd.name as confirm_user_name',
			'e.name as return_user_name',
			'f.name as arrive_user_name'
		);
		$where = Warehouse_Allocate::buildSearchWhere($condition);
		if ($cp == 0 && $ps == 0)
		{
			$select = Warehouse_Allocate::find($where)
				->joinLeft('warehouse as a', '', 'a.id=warehouse_allocate.start_warehouse_id')
				->joinLeft('warehouse as b', '', 'b.id=warehouse_allocate.end_warehouse_id')
				->joinLeft('user as c', '', 'c.id=warehouse_allocate.make_user_id')
				->joinLeft('user as d', '', 'd.id=warehouse_allocate.confirm_user_id')
				->joinLeft('user as e', '', 'e.id=warehouse_allocate.return_user_id')
				->joinLeft('user as f', '', 'f.id=warehouse_allocate.arrive_user_id')
				->setColumns($columns);
			$pagination = array();
		}
		else
		{
			$select = Warehouse_Allocate::find($where)
				->joinLeft('warehouse as a', '', 'a.id=warehouse_allocate.start_warehouse_id')
				->joinLeft('warehouse as b', '', 'b.id=warehouse_allocate.end_warehouse_id')
				->joinLeft('user as c', '', 'c.id=warehouse_allocate.make_user_id')
				->joinLeft('user as d', '', 'd.id=warehouse_allocate.confirm_user_id')
				->joinLeft('user as e', '', 'e.id=warehouse_allocate.return_user_id')
				->joinLeft('user as f', '', 'f.id=warehouse_allocate.arrive_user_id')
				->setColumns($columns)->limitPage($cp, $ps);
			$pagination = $select->getPagination();
		}
		$allocate = $select->order('warehouse_allocate.make_time desc')->asArray()->getAll();
		return array(
			'ack' => SUCCESS,
			'message' => '',
			'data' => $allocate,
			'pagination' => $pagination
		);
	}
	
	static function buildSearchWhere($condition)
	{
		$where = '1';
		if ( ! empty($condition['begin_create_time']))
		{
			$where .= ' and warehouse_allocate.make_time>=\'' . $condition['begin_create_time'] . '\'';
		}
		if ( ! empty($condition['end_create_time']))
		{
			$where .= ' and warehouse_allocate.make_time<=\'' . $condition['end_create_time'] . ' 23:59:59\'';
		}
		if ( ! empty($condition['begin_confirm_time']))
		{
			$where .= ' and warehouse_allocate.confirm_time>=\'' . $condition['begin_confirm_time'] . '\'';
		}
		if ( ! empty($condition['end_confirm_time']))
		{
			$where .= ' and warehouse_allocate.confirm_time<=\'' . $condition['end_confirm_time'] . ' 23:59:59\'';
		}
		if ( ! empty($condition['begin_arrive_time']))
		{
			$where .= ' and warehouse_allocate.arrive_time>=\'' . $condition['begin_arrive_time'] . '\'';
		}
		if ( ! empty($condition['end_arrive_time']))
		{
			$where .= ' and warehouse_allocate.arrive_time<=\'' . $condition['end_arrive_time'] . ' 23:59:59\'';
		}
		if ( ! empty($condition['begin_finance_audit_time']))
		{
			$where .= ' and warehouse_allocate.finance_audit_time>=\'' . $condition['begin_finance_audit_time'] . '\'';
		}
		if ( ! empty($condition['end_finance_audit_time']))
		{
			$where .= ' and warehouse_allocate.finance_audit_time<=\'' . $condition['end_finance_audit_time'] . ' 23:59:59\'';
		}
		if ( ! empty($condition['number']))
		{
			$where .= ' and warehouse_allocate.number=\'' . $condition['number'] . '\'';
		}
		if ( ! empty($condition['start_warehouse_id']))
		{
			$where .= ' and warehouse_allocate.start_warehouse_id=' . $condition['start_warehouse_id'];
		}
		if ( ! empty($condition['end_warehouse_id']))
		{
			$where .= ' and warehouse_allocate.end_warehouse_id=' . $condition['end_warehouse_id'];
		}
		if ( ! empty($condition['product']))
		{
			$item = Warehouse_Allocate_Item::find('product_basic.number=? or product_basic.name like ?', $condition['product'], '%'.$condition['product'].'%')
				->joinLeft('product_basic', '', 'product_basic.id=warehouse_allocate_item.product_basic_id')
				->asArray()->getAll();
			if ($item)
			{
				$alloacte_ids = array();
				foreach ($item as $i)
				{
					$allocate_ids[] = $i['warehouse_allocate_id'];
				}
				$where .= ' and warehouse_allocate.id in (' . implode(',', $allocate_ids) . ')';
			}
			else
			{
				$where .= ' and warehouse_allocate.id = 0';
			}
		}
		if ( ! empty($condition['finance_audit']))
		{
			$finance_audit_filter = '0';
			foreach (Q::ini('custom_flag/warehouse_allocate_finance_audit') as $o)
			{
				if (isset($condition['finance_audit'][$o['value']]) && $condition['finance_audit'][$o['value']] == $o['value'])
				{
					$finance_audit_filter .= ' or warehouse_allocate.finance_audit=' . $o['value'];
				}
			}
			$where .= ' and (' . $finance_audit_filter . ')';
		}
		if ( ! empty($condition['warehouse_allocate_status']))
		{
			$status_filter = '0';
			foreach (Q::ini('custom_flag/warehouse_allocate_status') as $s)
			{
				if (isset($condition['warehouse_allocate_status'][$s['value']]) && $condition['warehouse_allocate_status'][$s['value']] == $s['value'])
				{
					$status_filter .= ' or warehouse_allocate.status=' . $s['value'];
				}
			}
			$where .= ' and (' . $status_filter . ')';
		}
		return $where;
	}
}